package com.alex.controller;

import cn.hutool.db.Db;
import cn.hutool.db.Entity;
import cn.hutool.http.HttpUtil;
import com.alex.common.beans.ResultBean;
import com.alex.database_sql.entity.BasicJourMerge;
import com.alex.database_sql.entity.EarlyWarningJournal;
import com.alex.database_sql.entity.JidCitationSort;
import com.alex.database_sql.entity.PublicationDataSelect;
import com.alex.database_sql.mapper.BasicJourMergeMapper;
import com.alex.database_sql.mapper.EarlyWarningJournalMapper;
import com.alex.database_sql.mapper.JidCitationSortMapper;
import com.alex.database_sql.mapper.PublicationDataSelectMapper;
import com.alex.entityVo.JourSearchVo;
import com.alex.sevice.StaticService;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.sql.SQLException;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;


@RequestMapping("/search")
@RestController
@SuppressWarnings("ALL")
@Tag(name = "期刊推荐")
public class MainController {
    @Autowired
    private BasicJourMergeMapper basicJourMergeMapper;
    @Autowired
    private PublicationDataSelectMapper publicationDataSelectMapper;
    @Autowired
    private EarlyWarningJournalMapper earlyWarningJournalMapper;
    @Autowired
    private JidCitationSortMapper jidCitationSortMapper;

    @Resource
    StaticService staticService;



    public static String RESTURL_ES = "http://10.1.1.11:29000";

    public static String BASE_TABLE = "basic_jour_merge";


    public String auth_net_work(String title) {
        Map<String, Object> map = new HashMap<>();
        map.put("title", title);
        return HttpUtil.post(RESTURL_ES + "/journal_select/journal_select", map);
    }

    /*
    SELECT *
    FROM basic_jour_merge
    WHERE id IN (11, 12, 10)
    ORDER BY FIELD(id, 11, 12, 10);
    * */
    @Operation(summary = "期刊推荐", description = "输入标题,摘要,关键词,来进行检索推荐出期刊")
    @PostMapping(value = "select")
    public ResultBean<Object> select(@RequestBody JourSearchVo searchVo) {
        System.out.println("第一");
        Map<Integer, Integer> select = SelectJournalTitle.select(searchVo.getTitle(), searchVo.getKeyword(), searchVo.getAbs());
        System.out.println("第二");
        List<Integer> keys = new ArrayList<>();
        select.forEach((k, v) -> {
            keys.add(k);
        });
        System.out.println("初步检索的id的集合是 " + keys.size());

        staticService.insStat(searchVo.getTitle(), "期刊推荐");
        staticService.insStat(searchVo.getKeyword(), "期刊推荐");
        staticService.insStat(searchVo.getAbs(), "期刊推荐");


        if (keys.isEmpty()) {
            return new ResultBean<>();
        }
        LambdaQueryChainWrapper<BasicJourMerge> queryChainWrapper = new LambdaQueryChainWrapper<>(basicJourMergeMapper);
        //期刊基本信息
        queryChainWrapper.select(
                BasicJourMerge::getId,
                BasicJourMerge::getZkyLargeMin,//中科院大类分区最佳值
                BasicJourMerge::getJcrIf,//指数
                BasicJourMerge::getPublicationStartYear,//期刊初版年
                BasicJourMerge::getJour,//期刊名称
                BasicJourMerge::getIssn,//ISSN
                BasicJourMerge::getCiteScore,//引用评分
                BasicJourMerge::getCsSjr,//威望指数
                BasicJourMerge::getIncludeDb,//发文数据库
                BasicJourMerge::getLetProportion,//录用比例
                BasicJourMerge::getLetSpeed,//审稿速度
                BasicJourMerge::getLetJourContributeWebsite,//期刊投稿网站
                BasicJourMerge::getLetJourWebsite,//期刊官网
                BasicJourMerge::getLa//语种
        );

        queryChainWrapper.in(BasicJourMerge::getId, keys);
        //如果有中科院分区的筛选
        queryChainWrapper.eq(StringUtils.isNotEmpty(searchVo.getZky()), BasicJourMerge::getZkyLargeMin, searchVo.getZky());
        //如果有影响因子范围的筛选
        if (StringUtils.isNotEmpty(searchVo.getJif())) {
            String[] jif = searchVo.getJif().split("_");
            queryChainWrapper.ge(BasicJourMerge::getJcrIf, jif[0]);
            queryChainWrapper.le(BasicJourMerge::getJcrIf, jif[1]);
        }
        //排序
        if (null != searchVo.getShortFiled()) {
            //默认按照相关度排序
            if (searchVo.getShortFiled() == 1) {
                queryChainWrapper.orderByDesc(BasicJourMerge::getId);
            }
            //以影响因子排序
            if (searchVo.getShortFiled() == 2) {
                if (searchVo.getShortOrder() == 1) {
                    queryChainWrapper.orderByAsc(BasicJourMerge::getJcrIf);
                } else {
                    queryChainWrapper.orderByDesc(BasicJourMerge::getJcrIf);
                }
            }
            //以年份排序
            if (searchVo.getShortFiled() == 3) {
                if (searchVo.getShortOrder() == 1) {
                    queryChainWrapper.orderByAsc(BasicJourMerge::getPublicationStartYear);
                } else {
                    queryChainWrapper.orderByDesc(BasicJourMerge::getPublicationStartYear);
                }
            }
        }
        /**
         * 这里是依据标题 摘要 关键词 提起的期刊ID
         */
        List<BasicJourMerge> resultList = queryChainWrapper.list();

        Map<Integer, BasicJourMerge> map = resultList.stream().collect(Collectors.toMap(BasicJourMerge::getId, Function.identity()));

        resultList = keys.stream()
                .map(map::get)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());


        //尝试去es匹配标题,如果有的话,就把他的期刊放在第一个
        System.out.println("尝试去es匹配标题,如果有的话,就把他的期刊放在第一个");
        String jourId = auth_net_work(searchVo.getTitle());
        if (StringUtils.isNotEmpty(jourId)) {
            BasicJourMerge basicJourMerge = basicJourMergeMapper.selectById(jourId);
            resultList.add(0, basicJourMerge);
        }

        if (resultList.isEmpty()) {
            return new ResultBean<>();
        }
        //截取前20
        if (resultList.size() > 20) {
            resultList = resultList.subList(0, 20);
        }

        for (BasicJourMerge basicJourMerge : resultList) {

            Integer jid = basicJourMerge.getId();
            System.out.println("准备要补全的JID是" + jid);
            try {
                /**
                 * 期刊发行信息和期刊官网
                 */
                PublicationDataSelect publicationDataSelect = new LambdaQueryChainWrapper<>(publicationDataSelectMapper)

                        .select(PublicationDataSelect::getId,
                                PublicationDataSelect::getApcAmount,//货币金额
                                PublicationDataSelect::getApcCurrency,//货币名称
                                PublicationDataSelect::getAvgWeeksTilPublication,//平均周数

                                PublicationDataSelect::getCountry,//国家
                                PublicationDataSelect::getPublicationFrequency,//出版频率
                                PublicationDataSelect::getIssuesPerYear,//发行期数
                                PublicationDataSelect::getOpenAccess,//期刊OA信息
                                PublicationDataSelect::getPublicationLanguages//出版主要语种
                        )
                        .eq(PublicationDataSelect::getJid, jid).last("limit 1 ").one();
                if (null != publicationDataSelect) {
                    basicJourMerge.setPublicationDataSelect(publicationDataSelect);
                }
            } catch (Exception e) {
                System.out.println("期刊发行信息和期刊官网出错了");
                e.printStackTrace(System.err);
            }
            try {
                /**
                 * 是否是预警期刊  这个是list  有值的时候才展示这两个按钮
                 */
                List<EarlyWarningJournal> earlyWarningJournal = new LambdaQueryChainWrapper<>(earlyWarningJournalMapper)

                        .select(
                                EarlyWarningJournal::getId,
                                EarlyWarningJournal::getPublishingUnit,//发布机构
                                EarlyWarningJournal::getWarningLevel,//预警级别
                                EarlyWarningJournal::getYearOfPublication,//发布年份
                                EarlyWarningJournal::getPublicationDate,//发布日期
                                EarlyWarningJournal::getSourceUrl,//来源URL
                                EarlyWarningJournal::getSubject//学科
                        )
                        .eq(EarlyWarningJournal::getJid, jid).list();
                if (null != earlyWarningJournal) {
                    basicJourMerge.setEarlyWarningJournal(earlyWarningJournal);
                }
            } catch (Exception e) {
                System.out.println("是否是预警期刊出错了");
                e.printStackTrace(System.err);
            }
            try {
                /**
                 * 各大发文量
                 */
                JidCitationSort jidCitationSort = new LambdaQueryChainWrapper<>(jidCitationSortMapper)
                        .select(
                                JidCitationSort::getId,
                                JidCitationSort::getSelfCitationSum,//自引数量
                                JidCitationSort::getCitationSum,//被引数量
                                JidCitationSort::getChinaSum,//中国人发文数量
                                JidCitationSort::getChinaSort//中国人发文位次
                        )
                        .eq(JidCitationSort::getJid, jid).orderByDesc(JidCitationSort::getId).last(" limit 1").one();
                if (null != jidCitationSort) {
                    basicJourMerge.setJidCitationSort(jidCitationSort);
                }
            } catch (Exception e) {
                System.out.println("各大发文量出错了");
                e.printStackTrace(System.err);
            }
        }

        return new ResultBean<>(resultList);
    }

    @GetMapping(value = "detail")
    public ResultBean<Object> detail(Integer id) {
        try {
            List<Entity> query = Db.use("ai_study").query("select * from " + BASE_TABLE + " where id = ?", id);
            return new ResultBean<>(query.get(0));
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }


}
